home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-05-01 | 7.7 KB | 277 lines | [TEXT/MPS ] |
- //$P
- // UPatch.cp
- // Copyright © 1985-1991 by Apple Computer, Inc. All rights reserved.
-
- #include "UPatch.h"
- #include "UFailure.h"
- #include "Memory.h"
- #include "UMemory.h"
- #include "Textedit.h"
- #include "OSUtils.h"
- #include "UMacAppUtilities.h"
-
- TrapPatchPtr pPatchList = NULL; // global allocation declared in my header
-
- // System heap block record for PatchTrap
- typedef struct PTBlock
- {
- short Jmp;
- Ptr Routine;
- } *PTBlockPtr;
-
- // System heap block record for HeadPatch
- typedef struct TPBlock
- {
- short MoveL;
- long OldTrapAddr;
- short Jmp;
- Ptr Routine;
- } *TPBlockPtr;
-
- // System heap block record for Head1Patch
- typedef struct T1PBlock
- {
- long MoveParameter;
- short MoveL;
- long OldTrapAddr;
- short Jmp;
- Ptr Routine;
- } *T1PBlockPtr;
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAPatchRes
-
- Ptr AllocBlock(short blockSize,
- short theTrapNum,
- TrapPatch& thePatch)
-
- /* If blockSize is greater than zero, AllocBlock allocates a non-
- relocatable block in the system heap, of size blockSize. It then
- fills all fields of thePatch. If blockSize is zero, then no block
- is allocated and AllocBlock fills fields of thePatch. */
-
- {
- Ptr theBlock;
-
- if (blockSize > 0)
- theBlock = NewPermPtr(blockSize);
- else
- theBlock = NULL;
-
- thePatch.jmpPtr = theBlock;
- thePatch.oldTrapAddr = NGetTrapAddress(theTrapNum, GetTrapType(theTrapNum));
- thePatch.trapNum = theTrapNum;
- thePatch.nextPatch = pPatchList;
-
- pPatchList = &thePatch;
- return (theBlock);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAPatchRes
-
- pascal short PatchTrap(TrapPatch& thePatch,
- short theTrapNum,
- Ptr theRoutine)
-
- {
- PTBlockPtr patchBlock;
-
- patchBlock = (PTBlockPtr)AllocBlock(0, theTrapNum, thePatch);
- NSetTrapAddress((long)theRoutine, theTrapNum, GetTrapType(theTrapNum));
- return (noErr);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAPatchRes
-
- pascal short HeadPatch(TrapPatch& thePatch,
- short theTrapNum,
- Ptr theRoutine)
-
- {
- TPBlockPtr patchBlock;
-
- // Allocate the system heap block, and fill thePatch
- patchBlock = (TPBlockPtr)AllocBlock(sizeof(TPBlock), theTrapNum, thePatch);
-
- if (patchBlock != NULL)
- {
- // Stuff the code into the block
- patchBlock->MoveL = 0x2F3C; // MOVE.L #OldTrapAddr,-(SP)
- patchBlock->OldTrapAddr = thePatch.oldTrapAddr;
- patchBlock->Jmp = 0x4EF9; // JMP #Routine
- patchBlock->Routine = theRoutine;
-
- // Set the trap address to the block of code in the system heap
- NSetTrapAddress((long)patchBlock, theTrapNum, GetTrapType(theTrapNum));
- }
- return ((short)MemError());
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAPatchRes
-
- pascal short Head1Patch(TrapPatch& thePatch,
- short theTrapNum,
- Ptr theRoutine)
-
- {
- T1PBlockPtr patchBlock;
-
- // Allocate the system heap block, and fill thePatch
- patchBlock = (T1PBlockPtr)AllocBlock(sizeof(T1PBlock), theTrapNum, thePatch);
-
- if (patchBlock != NULL)
- {
- // Stuff the code into the block
- patchBlock->MoveParameter = 0x2F2F0004; // MOVE.L 4(SP),-(SP)
- patchBlock->MoveL = 0x2F3C; // MOVE.L #OldTrapAddr,-(SP)
- patchBlock->OldTrapAddr = thePatch.oldTrapAddr;
- patchBlock->Jmp = 0x4EF9; // JMP #Routine
- patchBlock->Routine = theRoutine;
-
- // Set the trap address to the block of code in the system heap
- NSetTrapAddress((long)patchBlock, theTrapNum, GetTrapType(theTrapNum));
- }
- return ((short)MemError());
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAPatchRes
-
- TrapPatchPtr GetPreviousPatchPtr(TrapPatchPtr thePatch)
- // walks the patch list backwards to return the patch record just prior to (*thePatchPtr) in the patch list
-
- {
- TrapPatchPtr tempPatchPtr = pPatchList;
-
- while ((tempPatchPtr != NULL) && (tempPatchPtr->nextPatch != thePatch))
- tempPatchPtr = tempPatchPtr->nextPatch;
- return (tempPatchPtr);
- }
-
-
- TrapPatchPtr GetNewerPatchPtr(TrapPatchPtr thePatch)
- // returns a newer patch record in the patch list which has the *same* trapNum as thePatch
-
- {
- TrapPatchPtr aPatchPtr = GetPreviousPatchPtr(thePatch);
-
- while ((aPatchPtr != NULL) && (aPatchPtr->trapNum != thePatch->trapNum))
- aPatchPtr = GetPreviousPatchPtr(aPatchPtr);
- return (aPatchPtr);
- }
-
-
- pascal void UnpatchTrap(TrapPatch& thePatch)
-
- {
- /* If this trap has a newer patch than the patch we're removing, then we have to take some extra
- special precautions. We have to muck with that patch's oldTrapAddr to point to this
- patch record's oldTrapAddr (for both the patch record and the jumpPtr code). We can pretty well
- ignore the case of an older patch on this same trap since the trapaddress in our patch record will
- be correct. */
- TrapPatchPtr newerPatchPtr = GetNewerPatchPtr(&thePatch);
-
- if (newerPatchPtr == NULL)
- // only set the trap address if there *isn't* a newer patch
- NSetTrapAddress(thePatch.oldTrapAddr, thePatch.trapNum, GetTrapType(thePatch.trapNum));
- else
- {
- // set up newerPatchPtr patch record so that it points to thePatch's OldTrapAddr
- newerPatchPtr->oldTrapAddr = thePatch.oldTrapAddr;
-
- // set up newerPatchPtr->jmpPtr code so that it jumps to where thePatch's code jumps to
- if (newerPatchPtr->jmpPtr != NULL)
- {
- if (*((LongIntPtr)(newerPatchPtr->jmpPtr)) == 0x2F2F0004)// is it a Head1Patch
- ((T1PBlockPtr)newerPatchPtr->jmpPtr)->OldTrapAddr = thePatch.oldTrapAddr;
- else if (*((IntegerPtr)(newerPatchPtr->jmpPtr)) == 0x2F3C)// is it a HeadPatch
- ((TPBlockPtr)newerPatchPtr->jmpPtr)->OldTrapAddr = thePatch.oldTrapAddr;
- else
- #if qDebug
- {
- /* Writeln('###In UnpatchTrap: can''t figure out what kind of patch ',
- ORD(newerPatchPtr), ' is!'); */
- // ProgramBreak('');
- }
- #endif
-
- ;
- }
- }
-
- // Unlink the patch from the linked list of patches
- if (&thePatch == pPatchList)
- pPatchList = thePatch.nextPatch;
- else
- {
- TrapPatchPtr aPatchPtr = pPatchList;
-
- while ((aPatchPtr != NULL) && (aPatchPtr->nextPatch != &thePatch))
- aPatchPtr = aPatchPtr->nextPatch;
- if (aPatchPtr != NULL) // Couldn't find thePatch, don't unpatch it
- aPatchPtr->nextPatch = thePatch.nextPatch;
- }
-
- // If the patch allocated a block in the system heap, deallocate it
- thePatch.jmpPtr = DisposeIfPtr(thePatch.jmpPtr);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAPatchRes
-
- pascal void UnpatchAll(void)
-
- {
- while (pPatchList != NULL)
- UnpatchTrap(*pPatchList);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAPatchRes
-
- pascal void EachPatchDo(pascal Boolean(* DoToPatch)(TrapPatchPtr thePatchPtr,
- void* staticLink),
- void* staticLink)
-
- {
- TrapPatchPtr aPatchPtr = pPatchList;
-
- while (aPatchPtr != NULL)
- {
- if (!DoToPatch(aPatchPtr, staticLink))
- aPatchPtr = aPatchPtr->nextPatch;
- else
- break;
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAPatchRes
-
- pascal void SetCallBack(ProcPtr targProc,
- long itsRefCon,
- CallBackPtr theCallBackPtr)
-
- /*
- 00000000: 2F17 '/.' MOVE.L (A7),-(A7) ; move old rtn address
- 00000002: 2F7C 1122 3344 '/|."3D' MOVE.L #$11223344,$0004(A7) ; plop refcon in
- 0004
- 0000000A: 4EF9 1122 3344 'N.."3D' JMP 0x11223344 ; shove off
- */
-
- {
- theCallBackPtr->saveRtnAdd = 0x2F17;
- theCallBackPtr->moveRefCon = 0x2F7C;
- theCallBackPtr->refCon = itsRefCon;
- theCallBackPtr->targOffset = 0x0004;
- theCallBackPtr->jmpInst = 0x4EF9;
- theCallBackPtr->jmpTarg = (long)targProc;
-
- // ??? should we flush the processor cache at this point?
- }
-
-
-